package com.qf.springbootssm.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.github.pagehelper.PageInfo;

import com.qf.springbootssm.entity.User;
import com.qf.springbootssm.service.UserService;
import com.qf.springbootssm.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

/**
 * @author manchi520
 * @date 2022/7/5
 * @apiNote
 */
@Controller
@RequestMapping("/user")
@Slf4j
@Api(tags = "用户Controller模块")
public class UserController {
    @Autowired
    private UserService userService;
    private LineCaptcha lineCaptcha;


    private DataResult dr; //定义返回前端数据格式约束

    /**
     * 登录验证
     * @param username
     * @param password
     * @param verifyCode
     * @return
     */
    @PostMapping("/login")
    @ResponseBody
    @ApiOperation("登录校验方法")
    public ResultVo login (String username, String password, String verifyCode, String autoLogin, HttpServletResponse resp, HttpSession session){
        log.debug("登录请求的入参：username={},password={}.verifyCode={}",username,password,verifyCode);
        log.debug("正确的验证码：{}",lineCaptcha.getCode());
        //1、校验参数是否为空
        if (StrUtil.hasBlank(username,password,verifyCode)){
            log.debug("参数校验失败，存在为空的参数");
            return ResultVo.fail("参数校验失败，存在为空的参数");
        }
        //2、校验验证码
        if (lineCaptcha.verify(verifyCode)){
            String pass = DigestUtil.md5Hex(password);
            log.debug("加密后的密码为：{}",pass);
            //3、校验用户名和密码，依赖UserService
            User user = userService.login(username, pass);

            //4、根据第三步的返回状态，封装最后返回的结果
            if (user != null){
                session.setAttribute("user",user);
                //判断用户是否选中了免登录
                if (autoLogin != null && autoLogin.equals("on")){
                    String userToken = username + "-" + password;
                    Cookie cookie = new Cookie("userToken",userToken);
                    //cookie.setPath该方法用于设置在同一个应用服务器内共享cookie（因为正常cookie只能由创建它的应用获得）
                    cookie.setPath("/");
                    cookie.setMaxAge(60*60*24*7);
                    log.debug("设置免登录cookie：{}",cookie);
                    resp.addCookie(cookie);
                }
                log.debug("登录成功，返回user={}",user);
                return ResultVo.ok("登录成功",user);
            }else {
                log.debug("登录失败，返回user={}",user);
                return ResultVo.fail("登录失败");
            }
        }else {
            log.debug("验证码校验失败，请求的验证码为：{}，正确验证码为：{}",verifyCode,lineCaptcha.getCode());
            return ResultVo.fail("验证码错误");
        }
    }

    /**
     * 获取登录和注册页面所需的验证码
     * @param resp
     * @throws IOException
     */
    @ApiOperation("获取验证码方法")
    @GetMapping("/getvcode")
    public void getVCode( HttpServletResponse resp) throws IOException {
        lineCaptcha = CaptchaUtil.createLineCaptcha(150, 50);
        //ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(150, 50, 4, 4);
        // 自定义验证码内容为四则运算方式
        /*captcha.setGenerator(new MathGenerator());
        req.getSession().setAttribute("verifyCode",captcha.getCode());*/
        //把验证码写出到浏览器
        lineCaptcha.write(resp.getOutputStream());
    }

    /**
     * 用户注册
     * @param userVo
     * @return
     */
    @PostMapping("/register")
    @ResponseBody
    @ApiOperation("用户注册方法")
    public ResultVo register(UserVo userVo){
        //1、校验前端传的参数是否有为空的值
        if (StrUtil.hasBlank(userVo.getName(),userVo.getPassword(),userVo.getSex(),
                userVo.getBirthday().toString(),userVo.getFilepath().toString(),userVo.getVerifyCode())) {
            log.debug("参数校验失败，存在为空的参数");
            return ResultVo.fail("参数校验失败，存在为空的参数");
        }
        //2、校验验证码是否正确
        if (lineCaptcha.verify(userVo.getVerifyCode())) {
            log.debug("验证码校验通过，开始调用service层nameRepeat方法判断用户名是否存在....");
            //判断用户是否已经注册过
            if (userService.nameRepeat(userVo) == null){
                //验证码正确则调用service层方法
                log.debug("该用户名不存在，开始调用register方法注册信息.....");
                User user = userService.register(userVo);
                if (user != null){
                    log.debug("用户注册成功，user={}",user);
                    return ResultVo.ok("注册成功",user);
                }else {
                    log.debug("用户注册失败");
                    return ResultVo.fail("注册失败");
                }
            }else {
                log.debug("该用户名已存在，请重新注册！");
                return ResultVo.fail("该用户名已存在，请重新注册！");
            }
        }else {
            log.debug("验证码错误，你输入的验证码为：{}",userVo.getVerifyCode());
            return ResultVo.fail("验证码错误");
        }
    }

    /**
     * 查询所有用户
     * @return
     */
    @GetMapping("/findAll")
    @ResponseBody
    @ApiOperation("查询所有方法")
    public DataResult findAll(HttpServletRequest req,HttpServletResponse resp,Integer currentPage,Integer pageSize) throws IOException {
        List<User> userList = userService.findAll(currentPage,pageSize);

        PageInfo page = new PageInfo(userList);

        return new DataResult(0,"查询成功",page.getTotal(),userList);
    }

    /**
     * 根据用户名查询某个用户（可模糊查询）
     * @param searchUserVo
     * @return
     */
    @PostMapping("/findByName")
    @ResponseBody
    @ApiOperation("根据用户名查询某个用户")
    public DataResult findByName(HttpServletRequest req, HttpServletResponse resp, SearchUserVo searchUserVo, Integer currentPage, Integer pageSize){
        List<User> userList = userService.findByName(currentPage,pageSize,searchUserVo);

        PageInfo page = new PageInfo(userList);
        return new DataResult(0,"查询成功",page.getTotal(),userList);
    }

    /**
     * 批量删除用户
     * @param arrIds
     * @return
     */
    @PostMapping("/deleteById")
    @ResponseBody
    @ApiOperation("批量删除用户")
    public ResultVo deleteById(@RequestParam(value = "arrIds[]") int[] arrIds){
        if (userService.deleteById(arrIds) > 0) {
            return ResultVo.ok("删除成功！");
        } else {
            return ResultVo.fail("删除失败！");
        }
    }

    /**
     * 添加用户
     * @param addUserVo
     * @return
     */
    @PostMapping("/addUser")
    @ResponseBody
    @ApiOperation("添加用户")
    public ResultVo addUser(AddUserVo addUserVo){
        int i = userService.addUser(addUserVo);
        if (i > 0){
            return ResultVo.ok("用户信息添加成功");
        }
        return ResultVo.fail("用户信息添加失败");
    }

    /**
     * 编辑修改用户信息
     * @param user
     * @return
     */
    @PostMapping("/updateUser")
    @ResponseBody
    @ApiOperation("编辑修改用户信息")
    public ResultVo updateUser(User user){
        int i = userService.updateUser(user);
        if (i > 0){
            return ResultVo.ok("用户信息修改成功");
        }
        return ResultVo.fail("用户信息修改失败");
    }

    @GetMapping("/logout")
    @SneakyThrows
    @ApiOperation("用户注销退出方法")
    public String logout(HttpServletRequest req, HttpServletResponse resp){
        HttpSession session = req.getSession();
        session.setAttribute("user",null);
        session.invalidate();
        Cookie[] cookies = req.getCookies();
        Cookie userCookie = new Cookie("userToken",null);
        userCookie.setMaxAge(0);
        resp.addCookie(userCookie);
        return "redirect:/index.html";
    }

    @GetMapping("/download")
    @ResponseBody
    @ApiOperation("下载方法")
    public ResultVo download() throws IOException {
        //先调用exportAll方法将数据库数据全部导出
        String fileName = userService.exportAll();
        log.debug("导出文件成功，filename={}", fileName);
        return ResultVo.ok("文件导出成功", fileName);
    }

    @GetMapping("/pic")
    public void getPic(HttpServletRequest req,HttpServletResponse resp) throws IOException {
        User user = (User) req.getSession().getAttribute("user");

        if (user != null){
            IOUtils.copy(new FileInputStream(user.getFilepath()),resp.getOutputStream());
        }
    }


    /**
     * 批量上传
     * @param file
     * @return
     * @throws IOException
     */
    @ApiOperation("文件批量上传方法")
    @PostMapping("/upload")
    public ResultVo uploadUser(MultipartFile file) throws IOException {

        Integer linesInsert =  userService.uploadUser(file);

        if (linesInsert>0){
            return ResultVo.ok("导入user数据成功",linesInsert);
        }else {
            return ResultVo.fail("没有导入任何user数据");
        }

    }
}
